﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.VisualBasic;

namespace _1242055_1242074
{
    public partial class Frm_Main : Form
    {
        #region Variable

        public List<string[]> dulieu = new List<string[]>();
        public List<string[]> lstMauHuanLuyen = new List<string[]>();
        public List<string[]> lstMau = new List<string[]>();
        public int k;
        public int m;

        #endregion

        #region Common

        public Frm_Main()
        {
            InitializeComponent();
        }

        #endregion

        #region Constant

        private const string TITLE_MSX = "Thông Báo";

        #endregion

        #region Event

        /// <summary>
        /// Load Form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Frm_Main_Load(object sender, EventArgs e)
        {
            if (dulieu.Count == 0)
            {
                btn_run.Enabled = false;
                btn_exportdata.Enabled = false;
            }
        }

        /// <summary>
        /// Open file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_open_Click(object sender, EventArgs e)
        {
            //Choose file
            OpenFileDialog openFile = new OpenFileDialog();
            openFile.Title = "Open file";
            openFile.InitialDirectory = System.Environment.CurrentDirectory;
            openFile.Filter = "CSV Files (.csv)|*.csv|All Files (*.*)|*.*";
            openFile.FilterIndex = 1;
            openFile.RestoreDirectory = true;

            if (openFile.ShowDialog() == DialogResult.OK)
            {
                //Xóa dữ liệu cũ
                dulieu.Clear();

                //Gán tên file
                txt_fileName.Text = openFile.FileName;
                docFile(openFile.FileName);
                if (dulieu.Count != 0)
                {
                    k = int.Parse(dulieu[0][0]);
                    m = int.Parse(dulieu[1][0]);
                    for(int i = 3; i < (3+m);i++)
                    {
                        lstMauHuanLuyen.Add(dulieu[i]);
                    }
                    lstMau.Add(dulieu[dulieu.Count -1]);
                    hienThiDuLieu();
                    btn_run.Enabled = true;
                }
            }
        }

        /// <summary>
        /// Close form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_exit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Run Process
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_run_Click(object sender, EventArgs e)
        {
            //Tính khoảng cách giữa d và tất cả các mẫu trong tập huấn luyện
            Dictionary<int, double> lstKhoanCach = new Dictionary<int, double>();
            for (int j = 0; j < lstMauHuanLuyen.Count(); j++)
            {
                lstKhoanCach.Add(j,khoanCach(j));
            }
            var ret = lstKhoanCach.OrderBy(i => i.Value).ToList();

            //Chọn k mẫu gần nhất với d trong tập huấn luyện
            List<int> lstIndex = new List<int>();
            int count = k;
            if (k > m)
            {
                count = ret.Count();
            }
            for (int i = 0; i < count; i++)
            {
                lstIndex.Add(ret[i].Key);
            }

            //Tìm lớp có nhiều mẫu nhất trong số k mẫu láng giềng
            Dictionary<string, int> lstPhanLop = new Dictionary<string,int>();
            dgv_dataTrainning.Rows.Clear();
            for (int index = 0; index < lstIndex.Count(); index++)
            {
                //Cập nhật danh sách mẫu gần nhất
                dgv_dataTrainning.Rows.Add(lstMauHuanLuyen[lstIndex[index]]);

                string lop = lstMauHuanLuyen[lstIndex[index]][lstMau[0].Length - 1];
                
                if (lstPhanLop.ContainsKey(lop))
                {
                    lstPhanLop[lop]++;
                }
                else
                {
                    lstPhanLop.Add(lop, 1);
                }
            }
            
            //Gán giá trị phân lớp cho mẫu
            var retPhanLop = lstPhanLop.OrderBy(i => i.Value).ToList();
            lstMau[0][lstMau[0].Length-1] = retPhanLop[retPhanLop.Count()-1].Key;          
            dgv_dataLearning.Rows.Clear();
            dgv_dataLearning.Rows.Add(lstMau[0]);
            MessageBox.Show("Successfuly!", TITLE_MSX, MessageBoxButtons.OK, MessageBoxIcon.Information);
            btn_exportdata.Enabled = true;
            btn_run.Enabled = false;
        }

        /// <summary>
        /// Export data
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_exportdata_Click(object sender, EventArgs e)
        {
            //Choose file
            SaveFileDialog saveFile = new SaveFileDialog();
            saveFile.Title = "Lưu file";
            saveFile.InitialDirectory = System.Environment.CurrentDirectory;
            saveFile.Filter = "CSV file (*.*)|*.csv*";
            saveFile.FileName = "Output.csv";
            saveFile.FilterIndex = 1;
            saveFile.RestoreDirectory = true;

            if (saveFile.ShowDialog() == DialogResult.OK)
            {
                string fileExportName = Path.GetFileName(saveFile.FileName);
                string path = Path.GetDirectoryName(saveFile.FileName);

                string ADD = "\\";

                string fileName = path + ADD + fileExportName;

                try
                {
                    FileSystem.FileOpen(1, fileName, OpenMode.Output, OpenAccess.Write, OpenShare.Shared, -1);
                    FileSystem.WriteLine(1, lstMau[0]);

                    FileSystem.FileClose(1);

                }
                catch (Exception)
                {
                    MessageBox.Show("Write file error!", TITLE_MSX, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    FileSystem.FileClose(1);
                    MessageBox.Show("Write file successfuly!", TITLE_MSX, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    btn_exportdata.Enabled = false;
                    txt_fileName.Clear();
                    dgv_dataTrainning.Rows.Clear();
                    dgv_dataTrainning.Columns.Clear();
                    dgv_dataLearning.Rows.Clear();
                    dgv_dataLearning.Columns.Clear();
                }
            }
        }

        #endregion

        #region Private Method

        
        /// <summary>
        ///Đọc dữ liệu từ file
        /// </summary>
        /// <param name="filePath"></param>
        private void docFile(string filePath)
        {
            try
            {
                string sFileContents = "";
                //Đọc hết dữ liệu trong file vào biến sFileContents.
                using (StreamReader oStreamReader = new StreamReader(File.OpenRead(filePath)))
                {
                    sFileContents = oStreamReader.ReadToEnd();//Đọc đến hết file
                }

                //Tách từng dòng dữ liệu ra. Gặp ký tự xuống dòng thì tách.
                string[] sFileLines = sFileContents.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                foreach (string sFileLine in sFileLines)//Duyệt qua từng dòng
                {//Mỗi dòng tương ứng
                    dulieu.Add(sFileLine.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));//Tách từng giá trị ra. Gặp dấu , thì tách ra
                }
                MessageBox.Show("Read file successfuly!", TITLE_MSX, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)//Lỗi đọc file
            {
                string message = "Read file error. Detail: \n" + ex.Message + "\n Plearse check again!";
                MessageBox.Show(message, TITLE_MSX, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        
        
        /// <summary>
        ///Hiện thị dữ liệu lên lưới
        /// </summary>
        private void hienThiDuLieu()
        {
            //Hiển thị dữ liệu huấn luyện
            dgv_dataTrainning.Columns.Clear();
            dgv_dataTrainning.Rows.Clear();
            dgv_dataTrainning.ColumnCount = dulieu[2].Length;
            for (int i = 0; i < dulieu[2].Length; i++)
            {
                dgv_dataTrainning.Columns[i].Name = dulieu[2][i].Replace("\"", "");
            }
            for (int j = 0; j < lstMauHuanLuyen.Count; j++)
            {
                dgv_dataTrainning.Rows.Add(lstMauHuanLuyen[j]);
            }

            //Hiển thị dữ liệu cần phân lớp
            dgv_dataLearning.Columns.Clear();
            dgv_dataLearning.Rows.Clear();
            dgv_dataLearning.ColumnCount = dulieu[2].Length;
            for (int i = 0; i < dulieu[2].Length; i++)
            {
                dgv_dataLearning.Columns[i].Name = dulieu[2][i].Replace("\"", "");
            }
            dgv_dataLearning.Rows.Add(lstMau[0]);

            for (int colIndex = 0; colIndex < dgv_dataLearning.Columns.Count; colIndex++)
            {
                for (int rowIndex = 0; rowIndex < dgv_dataLearning.Rows.Count - 1; rowIndex++)
                {
                    string temp = dgv_dataLearning.Rows[rowIndex].Cells[colIndex].Value.ToString();
                    switch (temp)
                    {
                        case "?":
                            dgv_dataLearning.Rows[rowIndex].Cells[colIndex].Style.ForeColor = Color.Red;
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        /// <summary>
        /// Khoản cách a đến b
        /// </summary>
        /// <param name="j"></param>
        /// <returns></returns>
        private double khoanCach(int j)
        {
            double s = 0;
            for (int index = 1; index < lstMau[0].Length-1; index++)
            {
                double a = Convert.ToDouble(lstMau[0][index]);
                double b = Convert.ToDouble(lstMauHuanLuyen[j][index]);
                s += (a - b)*(a-b);
            }
            return s;
         }

        #endregion

    }
}
